package cn.wubo.task.order.statistics.service.impl;

import cn.wubo.task.order.statistics.record.PersonCalendarRecord;
import cn.wubo.task.order.statistics.record.PersonCalendarResultRecord;
import cn.wubo.task.order.statistics.service.IDocumentService;
import cn.wubo.task.order.statistics.service.ITaskOrderPersonDateService;
import jakarta.annotation.Resource;
import org.apache.poi.ss.usermodel.*;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Map;
import java.util.Optional;

@Service
public class DocumentServiceImpl implements IDocumentService {

    @Resource
    ITaskOrderPersonDateService taskOrderPersonDateService;

    @Override
    public Workbook downloadPersonCalendar(PersonCalendarRecord record) {
        PersonCalendarResultRecord resultRecord = taskOrderPersonDateService.searchPersonCalendar(record.year(), record.personNames());

        try (InputStream resourceStream = getClass().getResourceAsStream("/document/template.xlsx")) {
            Path tempPath = Files.createTempFile("template" + System.currentTimeMillis(), ".xlsx");
            Files.copy(resourceStream, tempPath, StandardCopyOption.REPLACE_EXISTING);
            Workbook workbook = WorkbookFactory.create(tempPath.toFile());
            Sheet sheet = workbook.getSheetAt(0);

            CellStyle yellowCellStyle = workbook.createCellStyle();
            yellowCellStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
            yellowCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

            for (int i = 2; i < sheet.getPhysicalNumberOfRows(); i++) {
                String personName = sheet.getRow(i).getCell(2).getStringCellValue();
                if (record.personNames().contains(personName)) {
                    Optional<Map<String, String>> opt = resultRecord.data().stream().filter(e -> personName.equals(e.get("personName"))).findAny();
                    if (opt.isPresent()) {
                        Map<String, String> map = opt.get();
                        for (int j = 0; j < resultRecord.calendar().size(); j++) {
                            if ("1".equals(map.get(resultRecord.calendar().get(j)))) {
                                Cell cell = sheet.getRow(i).getCell(6 + j);
                                cell.setCellValue(1);
                                cell.setCellStyle(yellowCellStyle);
                            }
                        }

                        Cell formulaCell = sheet.getRow(i).getCell(6 + resultRecord.calendar().size());
                        FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
                        CellValue cellValue = evaluator.evaluate(formulaCell);
                        formulaCell.setCellValue(cellValue.getNumberValue());

                        Cell hour = sheet.getRow(i).getCell(7 + resultRecord.calendar().size());

                        // @formatter:off
                        resultRecord.hour()
                                .stream()
                                .filter(e -> personName.equals(e.get("personName"))
                                ).findAny()
                                .ifPresent(m ->
                                        hour.setCellValue(
                                                m.values()
                                                        .stream()
                                                        .filter(BigDecimal.class::isInstance).map(e -> (BigDecimal) e)
                                                        .reduce(BigDecimal.ZERO, BigDecimal::add)
                                                        .doubleValue()
                                        )
                                );
                        // @formatter:on
                    }
                }
            }

            return workbook;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
